/**
 * iptables-save 结果解析
 */
class IptablesSaveParser {
    /** */
    constructor ( data ) {
        this.data = data;
    }

    /** */
    setupIptablesData() {
        let iptables = {};
        iptables.filter = {
            INPUT : { default : {policy:'ACCEPT'}, chain : [] },
            FORWARD : { default : {policy:'ACCEPT'}, chain : [] },
            OUTPUT : { default : {policy:'ACCEPT'}, chain : [] },
        };
        iptables.nat = {
            PREROUTING : { default : {policy:'ACCEPT'}, chain : [] },
            POSTROUTING : { default : {policy:'ACCEPT'}, chain : [] },
            OUTPUT : { default : {policy:'ACCEPT'}, chain : [] },
        };
        iptables.mangle = {
            INPUT : { default : {policy:'ACCEPT'}, chain : [] },
            OUTPUT : { default : {policy:'ACCEPT'}, chain : [] },
            FORWARD : { default : {policy:'ACCEPT'}, chain : [] },
            PREROUTING : { default : {policy:'ACCEPT'}, chain : [] },
            POSTROUTING : { default : {policy:'ACCEPT'}, chain : [] },
        };
        iptables.raw = {
            PREROUTING : { default : {policy:'ACCEPT'}, chain : [] },
            OUTPUT : { default : {policy:'ACCEPT'}, chain : [] },
        };
        return iptables;
    }

    /**
     * 解析返回
     * @returns {object}
     */
    parse() {
        let dump = this.data + '';
        let iptables = this.setupIptablesData();

        let tableName = null;
        dump = dump.split('\r\n');
        for ( let i=0; i<dump.length; i++ ) {
            let line = dump[i];
            if ('' == line || '#' == line[0] || 'COMMIT' == line ) {
                continue;
            }

            // 处理表
            if ( '*' == line[0] ) {
                tableName = line.substring(1);
                if ( undefined == iptables[tableName] ) {
                    iptables[tableName] = {};
                }
                continue;
            }

            // 默认规则
            if ( ':' == line[0] ) {
                line = line.split(' ');
                let chainKey = line[0].substring(1);
                if ( undefined == iptables[tableName][chainKey] ) {
                    iptables[tableName][chainKey] = { default : {policy : line[1]}, chain : [] };
                }
                continue;
            }

            // 处理规则
            if ( '-A' == line.substring(0,2) ) {
                let item = this.parseRule(line);
                item.table = tableName;
                item.index = iptables[tableName][item.chain].chain.length + 1;
                iptables[tableName][item.chain].chain.push(item);
                continue;
            }

            throw "未知的数据格式：" + line;
        }

        return iptables;
    }

    /**
     * 解析规则
     * @param {*} line 
     */
    parseRule( line ) {
        let item = {
            index : null,
            table : null,
            chain : null,
            target : null,
            source : null,
            destination : null,
            comment : null,
            protocol : null,
            command : line,
            sport : null,
            dport : null
        };

        let parts = line.split(' ');
        while ( 0 < parts.length ) {
            let part = parts.shift();
            switch ( part ) {
            case '-A' : item.chain = parts.shift(); break;
            case '-s' : item.source = parts.shift(); break;
            case '-d' : item.destination = parts.shift(); break;
            case '-j' : item.target = parts.shift(); break;
            case '-p' : item.protocol = parts.shift(); break;
            case '-m' : this.parseRuleModule(parts, item); break;
            }
        }

        return item;
    }

    /**
     * 解析匹配模块
     * @param {*} parts 
     */
    parseRuleModule( parts, item ) {
        switch ( parts.shift() ) {
        case 'tcp' : this.parseRuleModuleTcp(parts, item); break;
        case 'comment' : this.parseRuleModuleComment( parts, item ); break;
        }
    }

    /** 备注 模块 */
    parseRuleModuleComment( parts, item ) {
        parts.shift();
        item.comment = [];
        do {
            let commentPart = parts.shift();
            item.comment.push(commentPart);
            if ( 1 == item.comment.length && '"' != commentPart[0] ) {
                item.comment[0] += '"';
                break;
            }
            if ( '"' == commentPart[commentPart.length-1] ) {
                break;
            }
        } while ( true );
        item.comment = item.comment.join(' ');
        item.comment = item.comment.substr(1, item.comment.length-2);
    }

    /** TCP 模块 */
    parseRuleModuleTcp( parts, item ) {
        item.comment = [];
        while ( true ) {
            let isDone = false;
            let tcpPart = parts[0];
            switch ( tcpPart ) {
            case '--sport' : parts.shift(); 
                item.sport = parts.shift();
                item.comment.push('来源端口:'+item.sport); 
                break;
            case '--dport' : 
                parts.shift(); 
                item.dport = parts.shift();
                item.comment.push('目标端口:'+item.dport); 
                break;
            default : isDone=true; break;
            }
            if ( isDone ) {
                break;
            }
        }
        item.comment = item.comment.join(' ');
    }
}

export default IptablesSaveParser;